package proxy;

import java.nio.ByteBuffer;

import com.Communicator;
import interfaces.*;
import core.*;

/**
 * Classe responsavel por receber e enviar mensagens
 *  
 * @author robertow
 *
 */
public class InterfaceProxy extends Thread implements IInterfaceProxy, IProxy{

	// Define um canal de comunicação para o procurador da interface
	private ICommunicator interfaceProxyChannel;
	
	// Define um canal de comunicação com o trabalhador da interface
	private ICommunicator workerChannelSend;
	
	// Define uma interface
	private Interface ifc;
	
	// Define um procurador para a interface
	static InterfaceProxy interfaceProxy;
	
	private String defaultIP;
	
	// Define uma identificação para o procurador da interface
	private String interfaceProxyId;
	
	// Descrição do canal de comunicação do procurador da interface
	private String interfaceProxyChannelDesc;
	
	private boolean running = true;

	// Descrição de um resultado de uma tarefa
	private byte[] resultDesc;
	
	// Tipo da mensagem
	private short msg_type;
	
	// Tamanho da mensagem
	private int size;
	private int descSize;
	
	// Identificação do trabalhador
	private String workerId;
	
	// Carga de trabalho de um trabalhador
	private int workerWorkload;
	
	// Capacidade de trabalho de um trabalhador
	private float workerCapacity;
	
	// Data em que o trablhador enviou seu estado
	private long workerUpdateDate;
	
	// Identificação da tarefa
	private String jobId;
	
	// Descrição do canal de um trabalhador
	private String channelDesc;

	public static void main(String[] args) {
		String id = args[0];
		String defaultIP = args[1];
		String launcherChannelDesc = args[2];

		if (args.length != 3) {
			System.out.println("Interface => ");
			System.out.println("\t Faltam argumentos (ID_NOH \n");
			System.exit(1);
		}

		interfaceProxy = new InterfaceProxy(id, defaultIP);

		try {
			ICommunicator launcherChannelSend = new Communicator();
			launcherChannelSend.connectServer(launcherChannelDesc);
			launcherChannelSend.sendMsgNodeStarted(launcherChannelSend.getSocket(), id, interfaceProxy.getChannelDesc());

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public InterfaceProxy(String interfaceProxyId, String defaultIP) {
		try {
			this.interfaceProxyId = interfaceProxyId;
			
			this.defaultIP = defaultIP;
			
			// Instancia um novo canal de comunicacao para a interface
			this.interfaceProxyChannel = new Communicator(this.defaultIP);
			
			// Obtem a descricao do canal 
			this.interfaceProxyChannelDesc = this.interfaceProxyChannel.serverChannelDescription();
			
			// Instancia uma nova interface
			this.ifc = new Interface(this.interfaceProxyId, this);
			
			System.out.println("InterfaceProxy iniciada =>");
			System.out.println("\t Seu id eh : " + this.interfaceProxyId);
			System.out.println("\t Seu canal eh: " + this.getChannelDesc() + "\n");
			
			this.start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void run() {
		try {
			ByteBuffer buf = null;
			
			/////////////////////////////////////////////////////////////////////////
			System.out.println("InterfaceProxy =>");
			System.out.println("\t Recebendo Mensagens ... \n");
			/////////////////////////////////////////////////////////////////////////
			while(this.running) {
				buf = this.interfaceProxyChannel.receiveMessages();
				msg_type = buf.getShort();
				size = buf.getInt();
				switch (msg_type) {
					case Config.NEW_WORKER:
						workerId = Communicator.readString(buf).trim();
						channelDesc = Communicator.readString(buf).trim();
						this.ifc.newWorker(workerId, channelDesc);
					break;
					
					case Config.JOB_RESULT:
						workerId = Communicator.readString(buf).trim();
						jobId = Communicator.readString(buf).trim();
						descSize = size - 2 - 4 - (workerId.length() + 1) - (jobId.length() + 1);
						resultDesc = new byte[descSize];
						buf.get(resultDesc);
						this.ifc.jobResult(workerId, jobId, resultDesc);
					break;
					
					 case Config.NODE_STATUS:
                         workerId = Communicator.readString(buf).trim();
                         workerWorkload = buf.getInt();
                         workerCapacity = buf.getFloat();
                         workerUpdateDate = buf.getLong();
                         this.ifc.nodeStatus(workerId, workerCapacity, workerWorkload, workerUpdateDate);
                     break;

										
					default:
						System.out.println("InterfaceProxy =>");
						System.out.println("\t\t LOST MESSAGE! Type: " + msg_type + "\n");
					break;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public void managerConnect(String channelDesc) {
		// TODO Auto-generated method stub
		try {
			this.workerChannelSend = new Communicator();
			this.workerChannelSend.connectServer(channelDesc);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void bossContactSend() {
		// TODO Auto-generated method stub
		try {
			this.workerChannelSend.sendMsgBossContact(this.workerChannelSend.getSocket(), this.getChannelDesc());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void newJobSend(IJob job) {
		// TODO Auto-generated method stub
		try {
			this.workerChannelSend.sendMsgNewJob(this.workerChannelSend.getSocket(), job.getID(), job.getDescription());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public void setChannelDesc(String channelDesc) {
		// TODO Auto-generated method stub
		this.interfaceProxyChannelDesc = channelDesc;
	}

	@Override
	public String getChannelDesc() {
		// TODO Auto-generated method stub
		return this.interfaceProxyChannelDesc;
	}

	@Override
	public void setChannel(ICommunicator channel) {
		// TODO Auto-generated method stub
		this.interfaceProxyChannel = channel;
	}

	@Override
	public ICommunicator getChannel() {
		// TODO Auto-generated method stub
		return this.interfaceProxyChannel;
	}
}
